home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / programm.ing / winlib.lzh / WINLIB / WINLIB.C < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-04  |  34.5 KB  |  1,137 lines

  1. /*
  2.  *    Main module
  3.  *
  4.  *    Copyright (c) Clever Bits and Bitgate Software 1993
  5.  *    All Rights Reserved.
  6.  *
  7.  *    The main module
  8.  *
  9.  *    Update log:
  10.  *
  11.  *    [20.12.92 - 12.9.93] Karl A. 0ygard
  12.  *        not documented
  13.  *    [24.9.93 - 8.10.93] Ken Hollis
  14.  *        WMsgWindow
  15.  *            WM_REDRAW        - put in window text stuff
  16.  *    [31.10.93 - 26.3.94] Ken Hollis and Karl 0ygard
  17.  *        WDoDial                - fixed and optimized cursor controls
  18.  *                            - removed 'handled' variable
  19.  *                            - removed just_created and WM_INIT stuff
  20.  *                            - optimised dragging of windows and stuff
  21.  *                            - removed call to WKillAllWindows at end
  22.  *                            - fixed bug in WM_TOPPED
  23.  *                            - changed code in WM_TOPPED; when background window
  24.  *                                is just _clicked_ it is topped - if mouse button
  25.  *                                is _pressed_ in window, objects in window are
  26.  *                                selected
  27.  *                            - removed two useless (and failing) lines from
  28.  *                                keyboard handler
  29.  *                            - moved keyboard equivalents into here
  30.  *                            - added help into the WDoDial feature
  31.  *                            - fixed all cursor stuff so it works
  32.  *                            - added form_alert for L_MOTIF look
  33.  *                            - fixed W_BEVENT for TOUCHEXIT buttons
  34.  *                                on background window events
  35.  *                            - FLYING object is now background movable
  36.  *                            - commented out global help for now
  37.  *                            - keyboard scrollable text windows
  38.  *                            - added double-click checking for desktop
  39.  *                            - made it so objects may be clicked in a
  40.  *                                topped window, but must be PRESSED in
  41.  *                                an untopped window.  Works better.
  42.  *                            - added SELECTABLE bit to TOUCHEXIT
  43.  *        WInit                - added setup for WAppl_Getinfo
  44.  *                            - added standard look at bootup
  45.  *                            - fixed EXTREMELY serious bug from nkcc
  46.  *                                nkc_init placement.  MUST BE AT THE
  47.  *                                END OF ANY PROCEDURE!
  48.  *                            - prgnameheader may be NULL. It is now allocated
  49.  *        WMsgWindow            - added iconification of window support
  50.  *                            - fixed WM_ARROWED stuff for text windows
  51.  *                            - added the WScrollText routine
  52.  *                            - finally fixed the amount_moved problems
  53.  *                            - moved WM_NEWTOP and WM_ONTOP
  54.  *                            - changed some code layout
  55.  *                            - added WM_PAINT
  56.  *            WM_REDRAW        - removed clipping
  57.  *            WM_CLOSED        - removed turn off of cursor - not necessary
  58.  *            WM_CREATED        - removed turn off of cursor - not necessary
  59.  *            WM_KILL            - removed turn off of cursor - not necessary
  60.  *                            - window is now relentlessly killed even if user
  61.  *                                tries to stop it.
  62.  *        WTerm                - fixed EXTREMELY serious bug from nkcc
  63.  *                                nkc_term placement.  MUST BE AT THE
  64.  *                                END OF ANY PROCEDURE!
  65.  *                            - made it nicer and more secure
  66.  *        WMenuBar            - removed, placed in MENU.C
  67.  *        (global)            - added new GEM 4.0+ messages
  68.  *        *prgnameheader        - moved from windows.c and renamed prgnameheader
  69.  *                                and added ": " for later use
  70.  */
  71.  
  72. #include <stdlib.h>
  73. #include <stddef.h>
  74. #include <string.h>
  75. #include <vdi.h>
  76. #include <stdio.h>
  77. #include <time.h>
  78.  
  79. #include "nkcc.h"
  80. #include "winlib.h"
  81.  
  82. #ifndef __WINLIB__
  83. #define __WINLIB__
  84. #endif
  85.  
  86. #ifdef __TURBOC__
  87. #pragma warn -pia
  88. #endif
  89.  
  90. GRECT desk;
  91. WINDOW *WindowChain;
  92. int Life, Return, VDIhandle, Ap_ID;
  93. char *desk_accessories[6];
  94. OBJECT *wl_menubar = NULL;
  95.  
  96. int gr_cw, gr_ch, gr_bw, gr_bh;
  97. int small_font, large_font, color_font;
  98. int num_colors, num_planes;
  99. int image_w, image_h, big_img;
  100. int    hotkeylevel, buttonlevel, ColSupported;
  101. int    WinLIBVersion, XVDIVersion, TextVersion, HotkeyVersion,
  102.     HottextVersion;
  103. char *prgnameheader;
  104. BOOL DesktopInstalled, MenusShown;
  105.  
  106. static char *___copyright =
  107. "*- WinLIB PRO Copyright © 1992-1994, Bitgate Software and Clever Bi"
  108. "ts.  All Rights Reserved.  This library is public domain, and may n"
  109. "ot be sold at any cost.  It may be sold with a program only if that"
  110. " program contains the library.  Programmed with Pure C 1.0 -*";
  111.  
  112. static char s1[] = " ";
  113. static char s2[] = "  XXXXXXXXXXXXXXXXX ";
  114. static char s3[] = "--------------------";
  115. static char s4[] = "  Desk Accessory 1 ";
  116. static char s5[] = "  Desk Accessory 2 ";
  117. static char s6[] = "  Desk Accessory 3 ";
  118. static char s7[] = "  Desk Accessory 4 ";
  119. static char s8[] = "  Desk Accessory 5 ";
  120. static char s9[] = "  Desk Accessory 6 ";
  121.  
  122. OBJECT menu_object[] = {
  123.   /* Tree #0*/
  124.   {  -1,   1,   4,0x0019,0x0000,0x0000, (long)(0x00000000L),   0,   0,  80,  25},
  125.   {   4,   2,   2,0x0014,0x0000,0x0000, (long)(0x00001100L),   0,   0,  80, 513},
  126.   {   1,   3,   3,0x0019,0x0000,0x0000, (long)(0x00000000L),   2,   0,   6, 769},
  127.   {   2,  -1,  -1,0x0020,0x0000,0x0000, (long)(s1),   0,   0,   6, 769},
  128.   {   0,   5,   5,0x0019,0x0000,0x0000, (long)(0x00000000L),   0, 769,  80,  23},
  129.   {   4,   6,  13,0x0014,0x0000,0x0000, (long)(0x00ff1100L),   2,   0,  20,   8},
  130.   {   7,  -1,  -1,0x001c,0x0000,0x0000, (long)(s2),   0,   0,  20,   1},
  131.   {   8,  -1,  -1,0x001c,0x0000,0x0008, (long)(s3),   0,   1,  20,   1},
  132.   {   9,  -1,  -1,0x001c,0x0000,0x0000, (long)(s4),   0,   2,  20,   1},
  133.   {  10,  -1,  -1,0x001c,0x0000,0x0000, (long)(s5),   0,   3,  20,   1},
  134.   {  11,  -1,  -1,0x001c,0x0000,0x0000, (long)(s6),   0,   4,  20,   1},
  135.   {  12,  -1,  -1,0x001c,0x0000,0x0000, (long)(s7),   0,   5,  20,   1},
  136.   {  13,  -1,  -1,0x001c,0x0000,0x0000, (long)(s8),   0,   6,  20,   1},
  137.   {   5,  -1,  -1,0x001c,0x0020,0x0000, (long)(s9),   0,   7,  20,   1}
  138. };
  139.  
  140. OBJECT *MainMenu = menu_object;
  141.  
  142. #define INTERNAL 0   /* Menu tree */
  143. #define DESKA1   8   /* STRING in Tree INTERNAL */
  144. #define DESKA2   9   /* STRING in Tree INTERNAL */
  145. #define DESKA3   10  /* STRING in Tree INTERNAL */
  146. #define DESKA4   11  /* STRING in Tree INTERNAL */
  147. #define DESKA5   12  /* STRING in Tree INTERNAL */
  148. #define DESKA6   13  /* STRING in Tree INTERNAL */
  149.  
  150. /*
  151.  *    Initialize everything
  152.  *
  153.  *    ap_id = application id returned by appl_init
  154.  *    DeskWndDispatcher = window dispatcher for desktop
  155.  *    DestBtnDispatcher = mouse button dispatcher for desktop
  156.  *    MainDispatcher = dispatcher for all program-specific messages
  157.  *    KeyDispatcher = main key dispatcher
  158.  *    prgname = name of program (used in MTOS only, may be left NULL)
  159.  *    prgnameheader = name of program to use in window titlebars (may be left NULL)
  160.  *
  161.  *    Returns TRUE on success
  162.  */
  163. GLOBAL int WInit(int ap_id, int *work_out, int DeskWndDispatcher(WINDOW *, int[]), int MainDispatcher(int[]), int KeyDispatcher(int), char *prgname, char *header, int dsk)
  164. {
  165.     int extnd_out[57], attr[10];
  166. /*    WLINFO wlinf[] = {0x0059, 0x0012, 0x0020, 0x0010, 0x0010};
  167.     COOKIE *newcook; */
  168.  
  169.     RFix_ObjectPos(MainMenu);
  170.  
  171.     if (AES_VERSION>0x0400) {
  172.         menu_bar(MainMenu, 1);
  173.  
  174.         desk_accessories[1] = (char *) MainMenu[DESKA1].ob_spec.free_string;
  175.         desk_accessories[2] = (char *) MainMenu[DESKA2].ob_spec.free_string;
  176.         desk_accessories[3] = (char *) MainMenu[DESKA3].ob_spec.free_string;
  177.         desk_accessories[4] = (char *) MainMenu[DESKA4].ob_spec.free_string;
  178.         desk_accessories[5] = (char *) MainMenu[DESKA5].ob_spec.free_string;
  179.         desk_accessories[6] = (char *) MainMenu[DESKA6].ob_spec.free_string;
  180.  
  181.         if (!strncmp((char *) desk_accessories[1], "  Desk Accessory", 16))
  182.             desk_accessories[1] = NULL;
  183.         if (!strncmp((char *) desk_accessories[2], "  Desk Accessory", 16))
  184.             desk_accessories[2] = NULL;
  185.         if (!strncmp((char *) desk_accessories[3], "  Desk Accessory", 16))
  186.             desk_accessories[3] = NULL;
  187.         if (!strncmp((char *) desk_accessories[4], "  Desk Accessory", 16))
  188.             desk_accessories[4] = NULL;
  189.         if (!strncmp((char *) desk_accessories[5], "  Desk Accessory", 16))
  190.             desk_accessories[5] = NULL;
  191.         if (!strncmp((char *) desk_accessories[6], "  Desk Accessory", 16))
  192.             desk_accessories[6] = NULL;
  193.  
  194.         menu_bar(MainMenu, 0);
  195.     } else {
  196.         desk_accessories[1] = "  Use accessories";
  197.         desk_accessories[2] = "  Use accessories";
  198.         desk_accessories[3] = "  Use accessories";
  199.         desk_accessories[4] = "  Use accessories";
  200.         desk_accessories[5] = "  Use accessories";
  201.         desk_accessories[6] = "  Use accessories";
  202.     }
  203.  
  204.     if (!(WindowChain = malloc(sizeof(WINDOW))))    /* Allocate memory for WindowChain */
  205.         return FALSE;
  206.  
  207.     WindowChain->next = NULL;
  208.     WindowChain->prev = NULL;
  209.  
  210.     wind_get(0, WF_WORKXYWH, &desk.g_x, &desk.g_y, &desk.g_w, &desk.g_h);
  211.     wind_get(0, WF_CURRXYWH, &WindowChain->size.g_x, &WindowChain->size.g_y, &WindowChain->size.g_w, &WindowChain->size.g_h);
  212.  
  213.     WindowChain->WndDispatcher = malloc(sizeof(DeskWndDispatcher));
  214.     WindowChain->WndDispatcher = DeskWndDispatcher;
  215.  
  216.     WindowChain->handle = 0;
  217.     WindowChain->state = W_OPEN | W_DESKTOP;
  218.  
  219.     WindowChain->kind = 0;
  220.     WindowChain->menubar = 0;
  221.     WindowChain->user = 0;
  222.  
  223.     WindowChain->timer.ev_mtcount = 0;
  224.     WindowChain->timer.user = 0;
  225.  
  226.     VDIhandle = graf_handle(&gr_cw, &gr_ch, &gr_bw, &gr_bh);
  227.     Ap_ID = ap_id;
  228.  
  229.     _MainDispatcher = malloc(sizeof(MainDispatcher));
  230.     _MainKeyDispatcher = malloc(sizeof(KeyDispatcher));
  231.  
  232.     _MainDispatcher = MainDispatcher;
  233.     _MainKeyDispatcher = KeyDispatcher;
  234.  
  235.     Life = TRUE;
  236.  
  237.     if (gr_cw < 7 || gr_ch < 7) {
  238.         image_w = gr_cw << 1;
  239.         image_h = gr_ch;
  240.         big_img = FAIL;
  241.     } else
  242.         if (gr_ch > 14) {
  243.             image_w = image_h = 16;
  244.             big_img = TRUE;
  245.         } else {
  246.             image_w = 16;
  247.             image_h = 8;
  248.             big_img = FALSE;
  249.         }
  250.  
  251.     init_images();
  252.  
  253.     vq_extnd(VDIhandle, 1, extnd_out);
  254.     init_mfdb(&screen, NULL, desk.g_w, desk.g_h, 0, work_out[4]);
  255.  
  256.     vqt_attributes(VDIhandle, attr);
  257.     num_planes = extnd_out[4];
  258.     num_colors = work_out[13];
  259.     large_font = attr[7];
  260.     color_font = attr[1];
  261.     small_font = work_out[46];
  262.  
  263.     ColSupported = work_out[13];    /* MultiTOS variable */
  264.     if (ColSupported < 0)
  265.         ColSupported = 32767;        /* True colour */
  266.  
  267. /*    create_cookie(&newcook, 'WLIB', (long) wlinf);
  268.     new_cookie(newcook); */
  269.  
  270.     if (header) {
  271.         prgnameheader = malloc(strlen(header) + 2);
  272.         strcpy(prgnameheader, header);
  273.         strcat(prgnameheader, ": ");
  274.     } else
  275.         prgnameheader = strdup("");
  276.  
  277.     hotkeylevel = HOTKEY_UNDERLINE;
  278.     buttonlevel = WS_XED;
  279.  
  280.     if (AES_VERSION >= 0x0400) {
  281.         shel_write(9, 0, 0x01, NULL, NULL);
  282.         if (_app && prgname)
  283.             menu_register(ap_id, prgname);
  284.     }
  285.  
  286.     if (num_colors>4)
  287.         Change3DType(L_MOTIF);
  288.     else
  289.         Change3DType(L_CUSTOM);
  290.  
  291.     WAppl_SetupInfo();
  292.  
  293.     if (dsk) {
  294.         DesktopInstalled = TRUE;
  295.         WSetup_Desktop();
  296.     }
  297.  
  298.     InitCookies();
  299.     TInitTitle();
  300.     WInitAlert();
  301.     WInitAscii();
  302.  
  303.     WindowChain->tree = desktop;
  304.  
  305.     if (DesktopInstalled)
  306.         WDesk_Redraw();
  307.  
  308.     WInitProcesses();
  309.     TShowTitle();
  310.  
  311.     nkc_init(NKI_NO200HZ, VDIhandle);
  312.  
  313.     return TRUE;
  314. }
  315.  
  316.  
  317. /*
  318.  *    Terminate
  319.  *
  320.  *    Frees all resources used by WinLIB.
  321.  */
  322. GLOBAL void WTerm(void)
  323. {
  324.     WKillAllWindows();
  325.     
  326.     free(prgnameheader);
  327.     free(_MainDispatcher);
  328.     free(_MainKeyDispatcher);
  329.     free(WindowChain);
  330.  
  331.     wind_set(0, WF_NEWDESK, 0);
  332.  
  333.     XVDI_RestoreForGEM();
  334.  
  335.     if (nkc_exit())
  336.         form_alert(1, "[3][Cannot terminate:   |NKCC not de-initialized][OK]");
  337. }
  338.  
  339.  
  340. /*
  341.  *    Terminate execution
  342.  *
  343.  *    returns = value to be returned by WDoDial()
  344.  *
  345.  *    Sends message to WDoDial loop to terminate.
  346.  */
  347. GLOBAL void WDie(int returns)
  348. {
  349.     Life = FALSE;
  350.     Return = returns;
  351. }
  352.  
  353.  
  354. /*
  355.  *    Search for window with handle 'handle'
  356.  *
  357.  *    Returns NULL if not found, pointer to actual window otherwise
  358.  */
  359. GLOBAL WINDOW *WFindHandle(int handle)
  360. {
  361.     WINDOW *ptr = WindowChain;
  362.  
  363.     while (ptr)
  364.         if (ptr->handle == handle)
  365.             return ptr;
  366.         else
  367.             ptr = ptr->next;
  368.  
  369.     return FALSE;
  370. }
  371.  
  372.  
  373. /*
  374.  *    Send a message to a window
  375.  *
  376.  *    win = Windows to send message to
  377.  *    msg_buf = message buffer (same syntax as ev_mgpbuff in evnt_mesag)
  378.  */
  379. GLOBAL void WMsgWindow(WINDOW *win, int msg_buf[8])
  380. {
  381.     int dummy;
  382.     int tophandle;
  383.  
  384.     WMoveWindow(win, -1, -1, -1, -1);
  385.  
  386.     switch (msg_buf[0]) {
  387.         GRECT *realrect, temp, work;
  388.         int pxyarray[4];
  389.  
  390.         case WM_REDRAW:    WWindGet(win, WF_TOP, &tophandle);
  391.                         if (win->edobject && win->edit_disp && win->handle == tophandle && !(win->state & W_MINIMIZED) && !(win->state & W_ICONIFIED)) {
  392.                             objc_edit(win->tree, win->edobject, 0, &win->edpos, ED_END);
  393.                             win->edit_disp = FALSE;
  394.                         }
  395.  
  396.                         realrect = (GRECT *) (msg_buf + 4);        /* nasty */
  397.  
  398.                         if (win->menubar) {
  399.                             int x, y;
  400.  
  401.                             WUpdateWindowMenu(win, msg_buf[4], msg_buf[5], msg_buf[6], msg_buf[7]);
  402.                             objc_offset(win->menubar, 1, &x, &y);
  403.                             dummy = max(msg_buf[5], y + win->menubar[1].ob_height + 1);
  404.                             if (dummy > msg_buf[5]) {
  405.                                 msg_buf[7] -= dummy - msg_buf[5];
  406.                                 msg_buf[5] = dummy;
  407.                             }
  408.                         }
  409.  
  410.                         if (rc_intersect(realrect, &desk)) {
  411.                             WWindGet(win, WF_WORKXYWH, &work.g_x, &work.g_y, &work.g_w, &work.g_h);
  412.  
  413.                             if (rc_intersect(realrect, &work))
  414.                                 if (msg_buf[7] > 0 && WCallWndDispatcher(win, msg_buf))
  415.                                     if (win->tree)
  416.                                         WUpdateWindowDlg(win, msg_buf[4], msg_buf[5], msg_buf[6], msg_buf[7], 0);
  417.                                     else {    
  418.                                         wind_update(BEG_UPDATE);
  419.                                         graf_mouse(M_OFF, NULL);
  420.  
  421.                                         vsf_interior(VDIhandle, FIS_SOLID);
  422.                                         vswr_mode(VDIhandle, MD_REPLACE);
  423.                                         vsf_color(VDIhandle, 0);
  424.  
  425.                                         WWindGet(win, WF_FIRSTXYWH, &temp.g_x, &temp.g_y, &temp.g_w, &temp.g_h);
  426.                                         while (temp.g_w && temp.g_h) {
  427.                                             if (rc_intersect(&temp, realrect)) {
  428.                                                 pxyarray[0] = temp.g_x;
  429.                                                 pxyarray[1] = temp.g_y;
  430.                                                 pxyarray[2] = temp.g_x + temp.g_w - 1;
  431.                                                 pxyarray[3] = temp.g_y + temp.g_h - 1;
  432.  
  433.                                                 v_bar(VDIhandle, pxyarray);
  434.                                             }
  435.                                             WWindGet(win, WF_NEXTXYWH, &temp.g_x, &temp.g_y, &temp.g_w, &temp.g_h);
  436.                                         }
  437.  
  438.                                         graf_mouse(M_ON, NULL);
  439.                                         wind_update(END_UPDATE);
  440.                                     }
  441.                         }
  442.  
  443.                         if (win->edobject && !win->edit_disp && win->handle == tophandle && !(win->state & W_MINIMIZED) && !(win->state & W_ICONIFIED)) {
  444.                             objc_edit(win->tree, win->edobject, 0, &win->edpos, ED_INIT);
  445.                             win->edit_disp = TRUE;
  446.                         }
  447.  
  448.                         msg_buf[0] = WM_PAINT;
  449.                         msg_buf[1] = Ap_ID;
  450.                         msg_buf[3] = win->handle;
  451.  
  452.                         WMsgWindow(win, msg_buf);
  453.  
  454.                         break;
  455.  
  456.         case WM_CLOSED:    if (WCallWndDispatcher(win, msg_buf)) {    
  457.                             WCruelCloseWindow(win, FALSE);
  458.                             WKillWindow(win);
  459.                         }
  460.  
  461.                         break;
  462.  
  463.         case WM_KILL:    WCallWndDispatcher(win, msg_buf);
  464.  
  465.                         if (win->state & W_OPEN)                /* Close window if it isn't already closed */
  466.                             WCruelCloseWindow(win, FALSE);
  467.  
  468.                         free(win->WndDispatcher);
  469.                         wind_delete(win->handle);                /* Delete window for good */
  470.  
  471.                         if (win->prev)                            /* Remove window from chain */
  472.                             win->prev->next = win->next;
  473.                         win->next->prev = win->prev;
  474.  
  475.                         if (WindowChain == win)                    /* Make sure WindowChain doesn't point to the removed window */
  476.                             WindowChain = win->next;
  477.  
  478.                         free(win);                                /* And free memory */
  479.  
  480.                         break;
  481.  
  482.         case WM_ICONIFY:if (WCallWndDispatcher(win, msg_buf)) {
  483.                             WWindSet(win, WF_ICONIFY, msg_buf[4], msg_buf[5], msg_buf[6], msg_buf[7]);
  484.                         }
  485.                         break;
  486.  
  487.         case WM_UNICONIFY:
  488.                         if (WCallWndDispatcher(win, msg_buf)) {
  489.                             WWindSet(win, WF_UNICONIFY, msg_buf[4], msg_buf[5], msg_buf[6], msg_buf[7]);
  490.                         }
  491.                         break;
  492.  
  493.         case WM_ALLICONIFY:
  494.                             /* Lots of work to do here... :( */
  495.                             /* But I've got the code! */
  496.                         break;
  497.  
  498.         case WM_BOTTOMED:
  499.         case WM_TOOLBAR:
  500.         case WM_NEWTOP:
  501.         case WM_ONTOP:
  502.         case WM_CREATED:WWindGet(win, WF_TOP, &tophandle);
  503.                         WCallWndDispatcher(win, msg_buf);
  504.                         break;
  505.  
  506.         case WM_PAINT:    WCallWndDispatcher(win, msg_buf);
  507.                         break;
  508.  
  509.         case WM_UNTOPPED:                                    /* nasty */
  510.         case WM_HSLID:    WWindGet(win, WF_TOP, &tophandle);
  511.                         if (win->edobject && win->edit_disp && win->handle == tophandle && !(win->state & W_MINIMIZED) && !(win->state & W_ICONIFIED)) {
  512.                             objc_edit(win->tree, win->edobject, 0, &win->edpos, ED_END);
  513.                             win->edit_disp = FALSE;
  514.                         }
  515.  
  516.                         WCallWndDispatcher(win, msg_buf);
  517.  
  518.                         if (win->edobject && !win->edit_disp && win->handle == tophandle && !(win->state & W_MINIMIZED) && !(win->state & W_ICONIFIED)) {
  519.                             objc_edit(win->tree, win->edobject, 0, &win->edpos, ED_INIT);
  520.                             win->edit_disp = TRUE;
  521.                         }
  522.                         break;
  523.  
  524.         case WM_ARROWED:WWindGet(win, WF_TOP, &tophandle);
  525.                         if (win->edobject && win->edit_disp && win->handle == tophandle && !(win->state & W_MINIMIZED) && !(win->state & W_ICONIFIED)) {
  526.                             objc_edit(win->tree, win->edobject, 0, &win->edpos, ED_END);
  527.                             win->edit_disp = FALSE;
  528.                         }
  529.  
  530.                         WCallWndDispatcher(win, msg_buf);
  531.  
  532.                         if (win->edobject && !win->edit_disp && win->handle == tophandle && !(win->state & W_MINIMIZED) && !(win->state & W_ICONIFIED)) {
  533.                             objc_edit(win->tree, win->edobject, 0, &win->edpos, ED_INIT);
  534.                             win->edit_disp = TRUE;
  535.                         }
  536.                         break;
  537.  
  538.         case WM_VSLID:    WWindGet(win, WF_TOP, &tophandle);
  539.                         if (win->edobject && win->edit_disp && win->handle == tophandle && !(win->state & W_MINIMIZED) && !(win->state & W_ICONIFIED)) {
  540.                             objc_edit(win->tree, win->edobject, 0, &win->edpos, ED_END);
  541.                             win->edit_disp = FALSE;
  542.                         }
  543.  
  544.                         WCallWndDispatcher(win, msg_buf);
  545.  
  546.                         if (win->edobject && !win->edit_disp && win->handle == tophandle && !(win->state & W_MINIMIZED) && !(win->state & W_ICONIFIED)) {
  547.                             objc_edit(win->tree, win->edobject, 0, &win->edpos, ED_INIT);
  548.                             win->edit_disp = TRUE;
  549.                         }
  550.                         break;
  551.  
  552.         case WM_SIZED:    WWindGet(win, WF_TOP, &tophandle);
  553.                         if (win->edobject && win->edit_disp && win->handle == tophandle && !(win->state & W_MINIMIZED) && !(win->state & W_ICONIFIED)) {
  554.                             objc_edit(win->tree, win->edobject, 0, &win->edpos, ED_END);
  555.                             win->edit_disp = FALSE;
  556.                         }
  557.  
  558.                         if (WCallWndDispatcher(win, msg_buf))
  559.                             WMoveWindow(win, -1, -1, msg_buf[6], msg_buf[7]);
  560.  
  561.                         if (win->edobject && !win->edit_disp && win->handle == tophandle && !(win->state & W_MINIMIZED) && !(win->state & W_ICONIFIED)) {
  562.                             objc_edit(win->tree, win->edobject, 0, &win->edpos, ED_INIT);
  563.                             win->edit_disp = TRUE;
  564.                         }
  565.                         break;
  566.  
  567.         case WM_MOVED:    if (WCallWndDispatcher(win, msg_buf))
  568.                             WMoveWindow(win, msg_buf[4], msg_buf[5], -1, -1);
  569.  
  570.                         break;
  571.  
  572.         case WM_TOPPED:    WWindGet(win, WF_TOP, &tophandle);
  573.                         if (win->edobject && win->edit_disp && win->handle == tophandle && !(win->state & W_MINIMIZED) && !(win->state & W_ICONIFIED)) {
  574.                             objc_edit(win->tree, win->edobject, 0, &win->edpos, ED_END);
  575.                             win->edit_disp = FALSE;
  576.                         }
  577.  
  578.                         if (WindowChain != win && ! (win->state & W_UNUNTOPPABLE) && WindowChain->state & W_UNUNTOPPABLE) {
  579.                             win = WindowChain;
  580.                             msg_buf[3] = win->handle;
  581.                         }
  582.  
  583.                         if (WCallWndDispatcher(win, msg_buf))
  584.                             WTopWindow(win);
  585.  
  586.                         if (win->edobject && !win->edit_disp && win->handle == tophandle && !(win->state & W_MINIMIZED) && !(win->state & W_ICONIFIED)) {
  587.                             objc_edit(win->tree, win->edobject, 0, &win->edpos, ED_INIT);
  588.                             win->edit_disp = TRUE;
  589.                         }
  590.                         break;
  591.  
  592.         case WM_FULLED:    WWindGet(win, WF_TOP, &tophandle);
  593.                         if (win->edobject && win->edit_disp && win->handle == tophandle && !(win->state & W_MINIMIZED) && !(win->state & W_ICONIFIED)) {
  594.                             objc_edit(win->tree, win->edobject, 0, &win->edpos, ED_END);
  595.                             win->edit_disp = FALSE;
  596.                         }
  597.  
  598.                         if (win->state & W_FULLERICONIFIES)
  599.                             WWindSet(win, WF_ICONIFY, !(win->state & W_ICONIFIED));
  600.                         else {
  601.                         if (WCallWndDispatcher(win, msg_buf))
  602.                             if (win->state & W_FULLERMINIMIZES)
  603.                                 WWindSet(win, WF_MINIMIZE, !(win->state & W_MINIMIZED));
  604.                             else {
  605.                                 int x, y, w, h;
  606.  
  607.                                 WWindGet(win, WF_CURRXYWH, &x, &y, &w, &h);
  608.                                 if (x == desk.g_x && y == desk.g_y && w == desk.g_w && h == desk.g_h)
  609.                                     WWindGet(win, WF_PREVXYWH, &x, &y, &w, &h);
  610.                                 else {
  611.                                     x = desk.g_x;
  612.                                     y = desk.g_y;
  613.                                     w = desk.g_w;
  614.                                     h = desk.g_h;
  615.                                 }
  616.  
  617.                                 WMoveWindow(win, x, y, w, h);
  618.                             }
  619.  
  620.                         if (win->edobject && !win->edit_disp && win->handle == tophandle && !(win->state & W_MINIMIZED) && !(win->state & W_ICONIFIED)) {
  621.                             objc_edit(win->tree, win->edobject, 0, &win->edpos, ED_INIT);
  622.                             win->edit_disp = TRUE;
  623.                         }
  624.                         }
  625.  
  626.                         break;
  627.  
  628.         case AP_DRAGDROP:
  629.                         WWindGet(win, WF_TOP, &tophandle);
  630.                         if (win->edobject && win->edit_disp && win->handle == tophandle && !(win->state & W_MINIMIZED) && !(win->state & W_ICONIFIED)) {
  631.                             objc_edit(win->tree, win->edobject, 0, &win->edpos, ED_END);
  632.                             win->edit_disp = FALSE;
  633.                         }
  634.  
  635.                         if (WCallWndDispatcher(win, msg_buf)) 
  636.                             WCallEtcDispatcher(msg_buf);
  637.  
  638.                         if (win->edobject && !win->edit_disp && win->handle == tophandle && !(win->state & W_MINIMIZED) && !(win->state & W_ICONIFIED)) {
  639.                             objc_edit(win->tree, win->edobject, 0, &win->edpos, ED_INIT);
  640.                             win->edit_disp = TRUE;
  641.                         }
  642.                         break;
  643.     }
  644. }
  645.  
  646.  
  647. /*
  648.  *    Main loop
  649.  *
  650.  *    This fetches messages from AES, interprets and
  651.  *    dispatches them to the correct windows.
  652.  *
  653.  *    The loop exits when a WDie() call is executed
  654.  *
  655.  *    Returns: The value specified in the WDie(value) call, or -1.
  656.  *             -1 means the application is to be terminated immediately,
  657.  *             the typical response to a AP_TERM message.
  658.  */
  659. GLOBAL int WDoDial(OBJECT *menu)
  660. {
  661.     EVENT event;
  662.  
  663.     Life = TRUE;
  664.     Return = 0;
  665.  
  666.     event.ev_mbclicks = 0x102;
  667.     event.ev_bmask = 3;
  668.     event.ev_mbstate = 0;
  669.  
  670.     if (menu) {
  671.         event.ev_mm1flags = FALSE;
  672.         event.ev_mm1x = menu->ob_x;
  673.         event.ev_mm1y = menu->ob_y;
  674.         event.ev_mm1width = menu->ob_width;
  675.         event.ev_mm1height = menu[1].ob_height;
  676.     }
  677.  
  678.     while (Life)
  679.     {
  680.         WINDOW *win;
  681.         int message;
  682.  
  683.         event.ev_mflags = MU_MESAG | MU_BUTTON | MU_KEYBD | MU_TIMER | MU_M1;
  684.  
  685.         event.ev_mtlocount = (int)(0x0001L);
  686.         event.ev_mthicount = (int)(0x0000L);
  687.  
  688.         if ((win!=NULL) && (win->timer.status)) {
  689.             long tcount;
  690.  
  691.             tcount = win->timer.clock - (clock() * 1000 / CLK_TCK);
  692.             
  693.             if (tcount > 0) {
  694.                 event.ev_mtlocount = (int) (tcount & 0xffffL);
  695.                 event.ev_mthicount = (int) (tcount >> 16);
  696.             } else
  697.                 event.ev_mtlocount = event.ev_mthicount = 0;
  698.         }
  699.  
  700.         message = EvntMulti(&event);
  701.  
  702.         win = WindowChain;
  703.  
  704.         if (message & MU_M1)
  705.             if (MenusShown)
  706.                 DoDeskMenu(menu);
  707.  
  708.         if ((message & MU_BUTTON) && ((wind_find(event.ev_mmox, event.ev_mmoy)) == DESKTOP) && (DesktopInstalled))
  709.             WDo_Desk(objc_find(desktop, 0, 10, event.ev_mmox, event.ev_mmoy), event.ev_mbreturn, TRUE);
  710.  
  711.         if (message & MU_MESAG) {
  712.             switch (event.ev_mmgpbuf[0]) {
  713.                 case WM_TOPPED:
  714.                     if (win = WFindHandle(event.ev_mmgpbuf[3])) {
  715.                         if (win->state & W_BEVENT) {
  716.                             int dummy;
  717.                             long applrecord[] =    {
  718.                                                     1, 0x010000L,
  719.                                                     0, 16,
  720.                                                     1, 0x100001L
  721.                                                 };
  722.                             GRECT rect;
  723.  
  724.                             graf_mkstate(&event.ev_mmox, &event.ev_mmoy, &event.ev_mmobutton, &event.ev_mmokstate);
  725.                             if (event.ev_mmobutton & 1) {
  726.                                 if (AES_VERSION > 0x0100)
  727.                                     appl_tplay(applrecord, 3, 100);
  728.                                 WMoveWindow(win, -1, -1, -1, -1);
  729.  
  730.                                 WWindGet(win, WF_WORKXYWH, &rect.g_x, &rect.g_y, &rect.g_w, &rect.g_h);
  731.                                 if (rc_inside(event.ev_mmox, event.ev_mmoy, &rect) && ! win->tree)
  732.                                     goto button;
  733.  
  734.                                 wind_get(win->handle, WF_WORKXYWH, &rect.g_x, &rect.g_y, &rect.g_w, &rect.g_h);
  735.                                 if (rc_inside(event.ev_mmox, event.ev_mmoy, &rect) && (
  736.                                         (win->tree && (dummy = objc_find(win->tree, 0, 99, event.ev_mmox, event.ev_mmoy)) != -1 &&
  737.                                             win->tree[dummy].ob_flags & (SELECTABLE | EXIT)) ||
  738.                                         (win->menubar && objc_find(win->menubar, 2, 1, event.ev_mmox, event.ev_mmoy) != -1))
  739.                                     )
  740. button:                            {
  741.                                     message |= MU_BUTTON;
  742.                                     event.ev_mbreturn = 1;
  743.                                 }
  744.  
  745.                                 if (win->tree[dummy].ob_flags & TOUCHEXIT) {
  746.                                     int type;
  747.  
  748.                                     graf_mkstate(&event.ev_mmox, &event.ev_mmoy, &type, &type);
  749.                                     dummy = objc_find(win->tree, 0, 99, event.ev_mmox, event.ev_mmoy);
  750.                                     if (dummy!=-1) {
  751.                                         type = win->tree[dummy].ob_type >> 8;
  752.                                         switch (type) {
  753.                                             case FLYING:
  754.                                                 graf_mouse(FLAT_HAND, NULL);
  755.                                                 WDragBox(win->size.g_w + 1, win->size.g_h + 1, win->size.g_x, win->size.g_y,
  756.                                                         desk.g_x, desk.g_y, -1, -1,
  757.                                                         BLACK, 0, 0x0000, &win->size.g_x, &win->size.g_y, TRUE);
  758.                                                 WMoveWindow(win, win->size.g_x, win->size.g_y, -1, -1);
  759.                                                 graf_mouse(ARROW, NULL);
  760.                                                 break;
  761.  
  762.                                             case HANDSLIDE:
  763.                                                 graf_mouse(FLAT_HAND, NULL);
  764.  
  765.                                             default:
  766.                                                 {
  767.                                                     int d, button;
  768.  
  769.                                                     if (win->tree[dummy].ob_flags & SELECTABLE)
  770.                                                         Objc_Change(win->tree, dummy, 0, win->tree[dummy].ob_state | SELECTED, 1);
  771.  
  772.                                                     do {
  773.                                                         graf_mkstate(&d, &d, &button, &d);
  774.                                                         WCallDlgDispatcher(win, dummy);
  775.                                                     } while (button);
  776.  
  777.                                                     if (win->tree[dummy].ob_flags & SELECTABLE)
  778.                                                         Objc_Change(win->tree, dummy, 0, win->tree[dummy].ob_state & ~SELECTED, 1);
  779.  
  780.                                                     if (type == HANDSLIDE)
  781.                                                         graf_mouse(ARROW, NULL);
  782.                                                 }
  783.                                                 break;
  784.                                         }
  785.                                     }
  786.                                 }
  787.                                 break;
  788.                             }
  789.                         }
  790.  
  791.                         WMsgWindow(win, event.ev_mmgpbuf);
  792.                     }
  793.                     break;
  794.  
  795.                 case WM_CLOSED:
  796.                     if (win = WFindHandle(event.ev_mmgpbuf[3]))
  797.                         WCloseWindow(win, WC_OBJECTABLE);
  798.                     break;
  799.  
  800.                 case WM_REDRAW:            /* Handle window messages */
  801.                 case WM_NEWTOP:
  802.                 case WM_ARROWED:
  803.                 case WM_VSLID:
  804.                 case WM_SIZED:
  805.                 case WM_FULLED:
  806.                 case WM_HSLID:
  807.                 case WM_MOVED:
  808.                 case WM_UNTOPPED:
  809.                 case WM_ONTOP:
  810.                 case WM_BOTTOMED:
  811.                 case WM_ICONIFY:
  812.                 case WM_UNICONIFY:
  813.                 case WM_ALLICONIFY:
  814.                 case WM_TOOLBAR:
  815.                 case WM_CREATED:
  816.                     if (win = WFindHandle(event.ev_mmgpbuf[3]))
  817.                         WMsgWindow(win, event.ev_mmgpbuf);
  818.                     break;
  819.  
  820.                 case AP_DRAGDROP:
  821.                     if (win = WFindHandle(event.ev_mmgpbuf[3]))
  822.                         WMsgWindow(win, event.ev_mmgpbuf);
  823.                     else
  824.                         WCallEtcDispatcher(event.ev_mmgpbuf);
  825.                     break;
  826.  
  827.                 case AC_OPEN:                /* Program/environmental messages */
  828.                 case AC_CLOSE:
  829.                 case SH_WDRAW:
  830.                 case CH_EXIT:
  831.                 case RESCH_COMPLETED:
  832.                 case AP_TERM:
  833.                     switch(event.ev_mmgpbuf[0]) {
  834.                         case AC_CLOSE:    if (WCallEtcDispatcher(event.ev_mmgpbuf))
  835.                                             WKillAllWindows();
  836.                                         break;
  837.  
  838.                         case AP_TERM:    if (WCallEtcDispatcher(event.ev_mmgpbuf))
  839.                                             return -2;
  840.                                         break;
  841.  
  842.                         case SH_WDRAW:
  843.                         case CH_EXIT:
  844.                         case RESCH_COMPLETED:
  845.                         case AC_OPEN:    WCallEtcDispatcher(event.ev_mmgpbuf);
  846.                                         break;
  847.                     }
  848.                     break;
  849.  
  850.                 case MN_SELECTED:        /* Menu messages */
  851.                     if (WCallEtcDispatcher(event.ev_mmgpbuf))
  852.                         menu_tnormal(wl_menubar, event.ev_mmgpbuf[3], 1);
  853.                     break;
  854.             }
  855.         }
  856.  
  857.         if (message & MU_TIMER) {
  858.             if (win->timer.status) {
  859.                 WStartTimer(win);
  860.                 WCallTmrDispatcher(win);
  861.             } else {
  862.                 int mx, my, co;
  863.  
  864.                 graf_mkstate(&mx,&my,&co,&co);
  865.                 co = objc_find(win->tree, 0, 99, mx, my);
  866.  
  867.                 if (co!=-1 && (win->state & W_OPEN))
  868.                     if (win->tree[co].ob_flags & EDITABLE)
  869.                         WGrafMouse(TEXT_CRSR);
  870.                     else
  871.                         WGrafMouse(ARROW);
  872.             }
  873.         }
  874.  
  875.         if ((message & MU_KEYBD) && !(win->state & W_MINIMIZED) && !(win->state & W_ICONIFIED)) {
  876.             int    n_key, nxtobj, nxtchr;
  877.  
  878.             win = WindowChain;
  879.             WMoveWindow(win, -1, -1, -1, -1);
  880.             n_key = nkc_tconv((event.ev_mkreturn & 0xff) | (((long) event.ev_mkreturn & 0xff00) << 8) | ((long) event.ev_mmokstate << 24));
  881.  
  882.             if ((n_key & NKF_ALT) && (n_key & NKF_CTRL)) {
  883.                 switch(n_key & 0xFF) {
  884.                     case NK_DEL:    if (n_key & NKF_RSH)
  885.                                         WCallResetDispatcher(win, 1);
  886.                                     else
  887.                                         WCallResetDispatcher(win, 0);
  888.  
  889.                                     goto exit_kbd;
  890.  
  891.                     case NK_UP:
  892.                     case '8':        if ((((n_key & 0xFF) == '8') && (n_key & NKF_NUM)) || ((n_key & 0xFF) == NK_UP)) {
  893.                                         int m[8];
  894.  
  895.                                         m[0] = WM_ARROWED;
  896.                                         m[4] = ((n_key & NKF_RSH) || (n_key & NKF_LSH)) ? WA_UPPAGE : WA_UPLINE;
  897.  
  898.                                         WMsgWindow(win, m);
  899.                                     }
  900.                                     goto exit_kbd;
  901.  
  902.                     case NK_DOWN:
  903.                     case '2':        if ((((n_key & 0xFF) == '2') && (n_key & NKF_NUM)) || ((n_key & 0xFF) == NK_DOWN)) {
  904.                                         int m[8];
  905.  
  906.                                         m[0] = WM_ARROWED;
  907.                                         m[4] = ((n_key & NKF_RSH) || (n_key & NKF_LSH)) ? WA_DNPAGE : WA_DNLINE;
  908.  
  909.                                         WMsgWindow(win, m);
  910.                                     }
  911.                                     goto exit_kbd;
  912.  
  913.                     case '*':        if ((n_key & NKF_NUM) && (win->handle!=0)) {
  914.                                         int m[8];
  915.  
  916.                                         m[0] = WM_FULLED;
  917.                                         m[3] = win->handle;
  918.  
  919.                                         WMsgWindow(win, m);
  920.                                     }
  921.                                     goto exit_kbd;
  922.  
  923.                     case NK_F5:        Change3DType(L_MULTITOS);
  924.                                     WRedrawAllWindows();
  925.                                     goto exit_kbd;
  926.  
  927.                     case NK_F6:        Change3DType(L_CUSTOM);
  928.                                     WRedrawAllWindows();
  929.                                     goto exit_kbd;
  930.  
  931.                     case NK_F7:        if (num_colors>4) {
  932.                                         Change3DType(L_MOTIF);
  933.                                         WRedrawAllWindows();
  934.                                     } else
  935.                                         WFormCustAlert(3,
  936.                                                         " Motif look ",
  937.                                                         "Sorry, the Motif 3D style look",
  938.                                                         "is  only available  in a color",
  939.                                                         "mode with  more than 4 colors.",
  940.                                                         "Please change mode or resolut-",
  941.                                                         "ions   to    see   the   mode.",
  942.                                                         " ", "Okay", " ");
  943.                                     goto exit_kbd;
  944.  
  945.                     case NK_F8:        Change3DType(L_GENEVA);
  946.                                     WRedrawAllWindows();
  947.                                     goto exit_kbd;
  948.  
  949.                     case NK_F9:        Change3DType(L_WINLIB);
  950.                                     WRedrawAllWindows();
  951.                                     goto exit_kbd;
  952.  
  953.                     case NK_F10:    Change3DType(L_STANDARD);
  954.                                     WRedrawAllWindows();
  955.                                     goto exit_kbd;
  956.  
  957.                     case ' ':        WRedrawAllWindows();
  958.                                     goto exit_kbd;
  959.  
  960.                     case NK_ESC:    WCloseWindow(win, WC_OBJECTABLE);
  961.                                     goto exit_kbd;
  962.  
  963.                     case NK_TAB:    WTopWindow(NULL);
  964.                                     goto exit_kbd;
  965.  
  966.                     case NK_BS:        WKillAllWindows();
  967.                                     goto exit_kbd;
  968.  
  969. /*                    case NK_HELP:    CallInternalHelp();
  970.                                     goto exit_kbd; */
  971.  
  972.                     case NK_ENTER:    {
  973.                                         int x, y, w, h;
  974.  
  975.                                         WWindGet(win, WF_WORKXYWH, &x, &y, &w, &h);
  976.                                         WRedrawWindow(win, x, y, w, h);
  977.                                     }
  978.  
  979.                                     goto exit_kbd;
  980.                 }
  981.             }
  982.  
  983.             if (win->state & W_OPEN) {
  984.                 if (WCallWKeyDispatcher(win, n_key))
  985.                     if (WCallKeyDispatcher(n_key))
  986.                         if (win->tree)
  987.                             if (WForm_keybd(win, event.ev_mkreturn, event.ev_mmokstate, &nxtobj, &nxtchr)) {
  988.                                 if (nxtchr)
  989.                                     objc_edit(win->tree, win->edobject, nxtchr, &win->edpos, ED_CHAR);
  990.                                 if (nxtobj != win->edobject) {
  991.                                     edit_off(win);
  992.                                     win->edobject = nxtobj;
  993.                                     edit_on(win);
  994.                                 }
  995.                             } else {
  996.                                 if (!(win->tree[nxtobj].ob_flags & RBUTTON))
  997.                                     Objc_Change(win->tree, nxtobj, 0, win->tree[nxtobj].ob_state ^ SELECTED, 1);
  998.                                 else {
  999.                                     int act = nxtobj, lst, new;
  1000.                                     OBJECT *obptr = win->tree + nxtobj;
  1001.  
  1002.                                     if (!(win->tree[nxtobj].ob_state & SELECTED))
  1003.                                         Objc_Change(win->tree, nxtobj, 0, win->tree[nxtobj].ob_state | SELECTED, 1);
  1004.  
  1005.                                     for(;;) {
  1006.                                         lst = act;
  1007.                                         new = obptr->ob_next;
  1008.  
  1009.                                         for(;;)    {
  1010.                                             act = new;
  1011.                                             obptr = win->tree + act;
  1012.  
  1013.                                             if (obptr->ob_tail == lst) {
  1014.                                                 new = obptr->ob_head;
  1015.                                                 lst = act;
  1016.                                             } else {
  1017.                                                 if (act == nxtobj)
  1018.                                                     goto rb_exit;
  1019.  
  1020.                                                 if ((obptr->ob_state & SELECTED) && (obptr->ob_flags & RBUTTON)) {
  1021.                                                     Objc_Change(win->tree, act, 0, obptr->ob_state ^ SELECTED, 1);
  1022.                                                     goto rb_exit;
  1023.                                                 } else break;
  1024.                                             }
  1025.                                         }
  1026.                                     }
  1027.                                 }
  1028.  
  1029.                                 if (!(win->tree[nxtobj].ob_flags & RBUTTON || win->tree[nxtobj].ob_type & 0x8000))
  1030.                                     Objc_Change(win->tree, nxtobj, 0, NORMAL, 1);
  1031.  
  1032. rb_exit:                        WCallDlgDispatcher(win, nxtobj);
  1033.                             }
  1034.             } else
  1035.                 WCallKeyDispatcher(n_key);
  1036.         }
  1037.  
  1038. exit_kbd:
  1039.         if ((message & MU_BUTTON) && !(win->state & W_MINIMIZED) && !(win->state & W_ICONIFIED)) {
  1040.             int nxtobj, tophandle;
  1041.  
  1042.             if (win = WFindHandle(wind_find(event.ev_mmox, event.ev_mmoy))) {
  1043.  
  1044.                 if (WindowChain->state & W_MODAL)
  1045.                     win = WindowChain;
  1046.  
  1047.                 WMoveWindow(win, -1, -1, -1, -1);
  1048.                 WWindGet(win, WF_TOP, &tophandle);
  1049.  
  1050.                 if (win->menubar && objc_find(win->menubar, 1, 1, event.ev_mmox, event.ev_mmoy) != -1)
  1051.                     domenu(win);
  1052.                 else
  1053.                     if (win->tree && (nxtobj = objc_find(win->tree, 0, 99, event.ev_mmox, event.ev_mmoy)) != -1 && event.ev_mbreturn==1)
  1054.                         if (win->tree[nxtobj].ob_flags & (SELECTABLE | EDITABLE)) {
  1055.                             WForm_button(win, nxtobj, event.ev_mbreturn, &nxtobj);
  1056.  
  1057.                             if (win->tree[nxtobj].ob_flags & EDITABLE && nxtobj != win->edobject)
  1058.                                 if (win->handle == tophandle) {
  1059.                                     int pos = win->edpos;
  1060.  
  1061.                                     edit_off(win);
  1062.                                     win->edobject = nxtobj;
  1063.                                     win->edpos = pos;
  1064.                                     edit_on(win);
  1065.                                 } else
  1066.                                     win->edobject = nxtobj;
  1067.  
  1068.                             if (win->tree[nxtobj].ob_flags & EDITABLE)
  1069.                                 if (win->handle == tophandle) {
  1070.                                     register char *t = win->tree[win->edobject].ob_spec.tedinfo->te_ptext;
  1071.                                     register int pos;
  1072.  
  1073.                                     t += pos = find_position(win->tree, win->edobject, event.ev_mmox);
  1074.  
  1075.                                     edit_pos(win, pos);
  1076.                                     win->edobject = nxtobj;
  1077.                                 } else win->edobject = nxtobj;
  1078.  
  1079.                             if (win->tree[nxtobj].ob_flags & SELECTABLE
  1080.                                 && !(win->tree[nxtobj].ob_flags & RBUTTON ||
  1081.                                      win->tree[nxtobj].ob_type & 0x8000))
  1082.                                     Objc_Change(win->tree, nxtobj, 0, NORMAL, 1);
  1083.  
  1084.                             if (win->tree[nxtobj].ob_flags & (EXIT | TOUCHEXIT))
  1085.                                 WCallDlgDispatcher(win, nxtobj);
  1086.                         } else
  1087.                             if (win->tree[nxtobj].ob_flags & TOUCHEXIT) {
  1088.                                 int type = win->tree[nxtobj].ob_type >> 8;
  1089.                                 int flag = win->tree[nxtobj].ob_flags;
  1090.                                 int dummy, button;
  1091.  
  1092.                                 if (type == FLYING) {
  1093.                                     int m[8];
  1094.  
  1095.                                     graf_mouse(FLAT_HAND, NULL);
  1096.                                     WDragBox(win->size.g_w + 1, win->size.g_h + 1, win->size.g_x, win->size.g_y,
  1097.                                         desk.g_x, desk.g_y, -1, -1,
  1098.                                         BLACK, 0, 0x0000, &win->size.g_x, &win->size.g_y, TRUE);
  1099.  
  1100.                                     m[0] = WM_MOVED;
  1101.                                     m[3] = win->handle;
  1102.                                     m[4] = win->size.g_x;
  1103.                                     m[5] = win->size.g_y;
  1104.                                     m[6] = win->size.g_w;
  1105.                                     m[7] = win->size.g_h;
  1106.  
  1107.                                     WMsgWindow(win, m);
  1108.  
  1109.                                     graf_mouse(ARROW, NULL);
  1110.                                 }
  1111.  
  1112.                                 if (flag & HANDSLIDE)
  1113.                                     graf_mouse(FLAT_HAND, NULL);
  1114.  
  1115.                                 if (type!=FLYING)
  1116.                                     Objc_Change(win->tree, nxtobj, 0, win->tree[nxtobj].ob_state | SELECTED, 1);
  1117.  
  1118.                                 do {
  1119.                                     graf_mkstate(&dummy, &dummy, &button, &dummy);
  1120.                                     WCallDlgDispatcher(win, nxtobj);
  1121.                                 } while (button == 1);
  1122.  
  1123.                                 if (type!=FLYING)
  1124.                                     Objc_Change(win->tree, nxtobj, 0, win->tree[nxtobj].ob_state & ~SELECTED, 1);
  1125.  
  1126.                                 if (flag & HANDSLIDE)
  1127.                                     graf_mouse(ARROW, NULL);
  1128.                             }
  1129.                     else
  1130.                         WCallBtnDispatcher(win, event.ev_mmox, event.ev_mmoy, event.ev_mmobutton, event.ev_mmokstate, event.ev_mbreturn);
  1131.             }
  1132.         }
  1133.     }
  1134.  
  1135.     return Return;
  1136. }
  1137.